// refs: https://blog.csdn.net/sinat_35272898/article/details/122511603
// refs: https://uniapp.dcloud.net.cn/api/request/websocket.html
// 由于适应全平台，所以使用uni的api创建websocket
// 但所有vue页面只能使用一个websocket
// TODO 每个websocket应该实现如下的内容
//      断线重连、消息队列、确认机制
//      暂时以实现框架为目标，稳定的消息队列、确认机制晚点补充
// TODO 一些bug整理如下
//      uni.closeSocket无法使用
//      this.ws.close()一般只能在H5使用
//      修改代码后,websocket重连会创建不同的session
//      同时又维护旧session，导致服务器嘎掉后不断重连
//      这个现象跟切换页面后类似，会重新连接两次(如果close生效的话)

export default {
    data(){
      return {
          wsUrl: "",
          ws: null,
          needConnect: true,  // 是否错误后关闭连接
          hasConnected: false,
          connectLock: false,
          socketMsgQueue: [],
          socketUploadInterval: null,
          socketOpen: null,
          socketClose: null,
          socketError: null,
          socketMsg: null
      }
    },
    methods: {
        socketInit(wsUrl, onOpen = null, onClose = null, onError = null, onMessage = null){
            this.wsUrl  = wsUrl

            if (this.wsUrl === null || this.wsUrl === ""){
                return false
            }

            let that = this
            this.ws = uni.connectSocket({
                url: that.wsUrl,
                success: ()=>{
                    console.log("socket created")
                    return that.ws
                }
            })

            this.socketOpen = (onOpen !== null) ? onOpen : that.wsOpenDefault
            uni.onSocketOpen(this.socketOpen)
            this.socketClose = (onClose !== null) ? onClose : that.wsCloseDefault
            uni.onSocketClose(this.socketClose)
            this.socketError = (onError !== null) ? onError : that.wsErrorDefault
            uni.onSocketError(this.socketError)
            this.socketMsg = (onMessage !== null) ? onMessage : that.wsMsgDefault
            uni.onSocketMessage(this.socketMsg)

        },
        socketReconnect(){
            if(!this.needConnect) return ;
            if(this.connectLock) return ;  // 防止多次冲连

            this.connectLock = true

            this.ws.close()

            let that = this
            setTimeout(()=>{
                that.socketInit(that.wsUrl, that.socketOpen, that.socketClose, that.socketError, that.socketMsg)
                that.connectLock = false
            }, 3000)
        },
        closeSocket(){
            this.needConnect = false
            this.ws.close()
        },
        sendMsgWithSocket(msg){
            this.socketMsgQueue.push(msg)
        },
        msgSendLoop(success = null, fail = null){
            let that = this
            this.socketUploadInterval = setInterval(()=>{
                if(that.hasConnected){
                    if(that.socketMsgQueue.length !== 0){
                        let msg = that.socketMsgQueue.shift()
                        uni.sendSocketMessage({
                            data: msg,
                            success: (success !== null) ? success : that.wsSendSuccessDefault,
                            fail: (fail !== null) ? fail : (res)=>{ that.socketMsgQueue.unshift(msg) }
                        })
                    }
                }
            }, 1500)
        },
        wsSendSuccessDefault(res){

        },
        wsOpenDefault(res){
            console.log("socket opened")
            this.hasConnected = true
        },
        wsCloseDefault(res){
            console.log("socket closed")
            this.socketReconnect()
        },
        wsErrorDefault(res){
            console.log("socket error")
            this.socketReconnect()
        },
        wsMsgDefault(res){
            console.log("A msg arrive", res.data)
        }
    }
}